<?php
namespace app\index\controller;
use app\classes\helper\FuyouHelp;
use app\classes\helper\Paymihua;
use app\classes\helper\ReportOrder;
use think\Controller;
use think\Db;
use Yansongda\Pay\Pay;
use think\facade\Request;
class Notify extends Controller
{

    /**
     * 查找订单
     * @param $where
     * @return mixed
     */
    private function getOrderAndTable($where)
    {
        $data['channel'] = 'zc';
        $data['order'] = Db::table('pay_order')->where($where)->findOrEmpty();

        if (!$data['order']) {
            $data['order'] = Db::table('pay_order_kl_backups')->where($where)->findOrEmpty();
            if ($data['order']) {
                $data['channel'] = 'kl';
            }
        }
        return $data;
    }

    /**
     * 更新保护器
     * @param $quickId
     * @param $uid
     */
    private function refProtectDay($quickId, $uid)
    {
        $protectDay = Db::table("quick_app_info")->where("quick_id", $quickId)->value('protect_day');
        if ($protectDay) {
            $currentDate = date('Y-m-d H:i:s');
            $sevenDaysLater = strtotime("+{$protectDay} days", strtotime($currentDate));
            $exp_time = date('Y-m-d H:i:s', $sevenDaysLater);
            $table_uinfo = intval(substr($quickId,-2));
            Db::table('quick_user')->where('id', $uid)->setField('exp_time', $exp_time);
            Db::table($table_uinfo)->where('id', $uid)->setField('exp_time', $exp_time);
        }
    }

    /*
     * 米花支付异步回调
     * */
    public function miHua()
    {
        libxml_disable_entity_loader(true);

        $param      = request()->param();
        $merAccount = $param['merAccount'];
        $encodeData = $param['data'];
        $orderId    = $param['orderId'];

        if (!$merAccount) {
            die('401');
        }

        $paymentNumber  = Db::table('quick_payment_number')->where('mer_account',$merAccount)->where("payment_type", 2)->findOrEmpty();

        $server         = new Paymihua();
        $decryptData    = $server->newMhCheckSign($encodeData, $paymentNumber);

        if (empty($decryptData) || $decryptData['orderStatus'] != 'SUCCESS') {
            die('401');
        }

        // 订单解密
        $orderData = $server->newMhGetOrder($decryptData, $paymentNumber);
        if ($orderData['code'] != '000000') {
            die('402');
        }

        $result = $orderData['data']; // 微信支付订单号
        $where[] = ['out_trade_no', '=', $result['orderId']];
        $where[] = ['status', '=', 1];
        $oat = $this->getOrderAndTable($where);
        $order = $oat['order'];

        if (!$order){
            header("Content-type: text/html; charset=utf-8");
            echo 'SUCCESS';
            exit;
        }

        $user = Db::table('quick_user')->where('id',$order['uid'])
            ->field('id,quick_id,vip_exp_time')->findOrEmpty();

        $res = $this->orderHand($order, $user, $result['orderId']);

        if ($res) {
            header("Content-type: text/html; charset=utf-8");
            echo 'SUCCESS';
            exit;
        }
    }

    /**
     * 原生回调
     * @return \Symfony\Component\HttpFoundation\Response
     * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException
     * @throws \Yansongda\Pay\Exceptions\InvalidSignException
     */
    public function weChatNative()
    {
        $payId = input('payId');
        $wxConfig = [
            'appid' => '', // APP APPID
            'app_id' => '', // 公众号 APPID
            'miniapp_id' => '', // 小程序 APPID
            'mch_id' => '',
            'key' => '',
            'notify_url' => '',
            'cert_client' => '', // optional, 退款，红包等情况时需要用到
            'cert_key' => '',// optional, 退款，红包等情况时需要用到
            'log' => [ // optional
                'file' => './logs/wechat.log',
                'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
                'type' => 'single', // optional, 可选 daily.
                'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
            ],
            'http' => [ // optional
                'timeout' => 5.0,
                'connect_timeout' => 5.0,
                // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
            ]
        ];

        $paymentNumber = Db::table('quick_payment_number')->where('id',$payId)->findOrEmpty();
        if (!$paymentNumber) {
            echo "paymentNumber error";
            die;
        }

        if ($paymentNumber['pay_style'] == 1) {
            $wxConfig['app_id'] = $paymentNumber['app_id'];
        } else {
            $wxConfig['appid'] = $paymentNumber['app_id'];//未尝试
        }

        $wxConfig['mch_id'] = $paymentNumber['mch_id'];
        $wxConfig['key']    = $paymentNumber['apiv3'];
        $wechat = Pay::wechat($wxConfig);
        $result = $wechat->verify();
        $result = json_decode($result, true);

        $where[] = ['out_trade_no', '=', $result['out_trade_no']];
        $where[] = ['status', '=', 1];
        $oat    = $this->getOrderAndTable($where);
        $order  = $oat['order'];

        if (!$order){
            echo "order error";die;
        }

        $user = Db::table('quick_user')->where('id',$order['uid'])
            ->field('id,quick_id,vip_exp_time')->findOrEmpty();

        if ($result['result_code'] == 'SUCCESS') {

            $res = $this->orderHand($order, $user, $result['transaction_id']);

            if ($res) {
                return $wechat->success()->send();
            }
        }
    }

    /**
     * 原生支付宝回调
     * @return \Symfony\Component\HttpFoundation\Response
     * @throws \Yansongda\Pay\Exceptions\InvalidConfigException
     * @throws \Yansongda\Pay\Exceptions\InvalidSignException
     */
    public function aliNative()
    {
        $payId = input('payId');
        $zfbConfig = [
            'app_id' => '',
            'notify_url' => '',
            'return_url' => '',
            'ali_public_key' => '',
            'private_key' => '',
            'log' => [ // optional
                'file' => './logs/alipay.log',
                'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
                'type' => 'single', // optional, 可选 daily.
                'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
            ],
            'http' => [ // optional
                'timeout' => 5.0,
                'connect_timeout' => 5.0,
                // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
            ],
            // 'mode' => 'dev', // optional,设置此参数，将进入沙箱模式
        ];

        $paymentNumber = Db::table('quick_payment_number')->where('id',$payId)->findOrEmpty();
        if (!$paymentNumber) {
            echo "paymentNumber error";
            die;
        }

        $zfbConfig['app_id']            = $paymentNumber['app_id'];
        $zfbConfig['ali_public_key']    = $paymentNumber['public_key'];
        $zfbConfig['private_key']       = $paymentNumber['private_key'];

        $alipay = Pay::alipay($zfbConfig);
        $result = $alipay->verify();
        $result = json_decode($result, true);
        $where[] = ['out_trade_no', '=', $result['out_trade_no']];
        $where[] = ['status', '=', 1];

        $oat = $this->getOrderAndTable($where);
        $order = $oat['order'];
        if (!$order){
            echo "order error";
            die;
        }

        $user = Db::table('quick_user')->where('id',$order['uid'])
            ->field('id,quick_id,vip_exp_time')->findOrEmpty();

        if ($result['trade_status'] == 'TRADE_SUCCESS') {

            $res = $this->orderHand($order, $user, $result['trade_no']);

            if ($res) {
                return $alipay->success()->send();
            }
        }
    }

    /**
     * 富友回调
     */
    public function fuYou()
    {
        $data = file_get_contents("php://input");
        if ($data) {
            $data = json_decode($data, true);
            if ($data['resp_code'] == '0000') {
                $paymentNumber  = Db::table('quick_payment_number')->where("mer_no", $data['mchnt_cd'])->where("payment_type", 3)->findOrEmpty();
                $fyHelp         = new FuyouHelp($paymentNumber['public_key'], $paymentNumber['private_key']);
                $message        = $fyHelp->privateDecryptRsa($data['message']);
                $message        = json_decode($message, true);
                $out_trade_no   = $message['order_id'];

                $where[] = ['out_trade_no', '=', $out_trade_no];
                $where[] = ['status', '=', 1];
                $oat = $this->getOrderAndTable($where);
                $order = $oat['order'];

                if (!$order){
                    echo "order error";
                    die;
                }

                $user = Db::table('quick_user')->where('id',$order['uid'])
                    ->field('id,quick_id,vip_exp_time')->findOrEmpty();

                if ($message['order_st'] == 1) {

                    $res = $this->orderHand($order, $user, $message['pay_ssn']);

                    if ($res) {
                        echo 'SUCCESS';
                        exit;
                    } else {
                        echo 'FAIL';
                        exit;
                    }
                }
            }
        }
    }

    /**
     * 订单处理
     * @param $order
     * @param $user
     * @param $tradeNo
     * @return bool
     */
    private function orderHand($order, $user, $tradeNo)
    {
        if($order['status'] == 2)
        {
            //订单已支付无需重复处理
            return true;
        }

        $data_success               = $order;
        $data_success['order_id']   = $order['id'];

        unset($data_success['id']);

        $virtual_currency   = $order['virtual_currency'];
        $point_gift         = $order['point_gift'];
        $vipdays            = $order['vipdays'];

        $table_uinfo        = 'quick_user_'.intval(substr($user['quick_id'],-2));
        $UserPointsLogic    = \think\facade\App::model('UserBookPoints', 'logic');

        Db::startTrans();
        try {
            if ($point_gift > 0) {
                $UserPointsLogic->givePoint($user['id'], $point_gift, 1, 0);
            }
            if ($virtual_currency > 0) {
                //Db::table($table_uinfo)->where('id', $user['id'])->setInc('book_coin', $virtual_currency);
                Db::table('quick_user')->where('id', $user['id'])->setInc('book_coin', $virtual_currency);
            }

            if ($vipdays > 0) {

                $time = time();

                if ($user['vip_exp_time'] > $time) {
                    $vip_exp_time = $user['vip_exp_time'] + $vipdays * 86400;
                } else {
                    $vip_exp_time = $time + $vipdays * 86400;
                }

                //Db::table($table_uinfo)->where('id', $user['id'])->setField('vip_exp_time', $vip_exp_time);
                Db::table('quick_user')->where('id', $user['id'])->setField('vip_exp_time', $vip_exp_time);

            }

            //Db::table($table_uinfo)->where('id', $user['id'])->setInc('pay_times');
            Db::table('quick_user')->where('id', $user['id'])->setInc('pay_times');
            //Db::table($table_uinfo)->where('id', $user['id'])->setInc('pay_money', $order['total_fee']);
            Db::table('quick_user')->where('id', $user['id'])->setInc('pay_money', $order['total_fee']);

            //$this->refProtectDay($order['quick_id'], $user['id']);//更新保护期-暂弃用

            $uoWhere[] = ['uid', '=', $user['id']];
            $uoWhere[] = ['status', '=', 2];
            $payCount = Db::table("pay_order")->where($uoWhere)->count();
            $pay_time = time();

            Db::table("pay_order")->where("id", $order['id'])->update([
                'status'            => 2,
                'pay_time'          => $pay_time,
                'recharge_times'    => $payCount + 1,
                'trade_no'          => $tradeNo
            ]);

            $data_success['trade_no']       = $tradeNo;
            $data_success['recharge_times'] = $payCount + 1;
            $data_success['pay_time']       = $pay_time;
            $data_success['status']         = 2;

            Db::table("pay_order_success")->insert($data_success);

            //书籍充值次数
            if ($order['nid'] > 0) {
                $flag = Db::table("rp_novel_recharge_repeat_detail")->where("nid", $order['nid'])->where("uid", $order['uid'])->find();
                if (!$flag) {
                    Db::table("rp_novel_recharge_repeat_detail")->insert([
                        'qid' => $order['quick_id'],
                        'nid' => $order['nid'],
                        'uid' => $order['uid'],
                        'pay_count' => 1,
                    ]);
                } else {
                    Db::table("rp_novel_recharge_repeat_detail")->where("nid", $order['nid'])->where("uid", $order['uid'])->setInc('pay_count');
                }
            }

            //真实用户充值信息
            $payRecord = Db::table("quick_pay_user_record")->where("uid", $user['id'])->find();
            if ($payRecord) {
                Db::table("quick_pay_user_record")->where("uid", $user['id'])->setInc('pay_money', $order['total_fee']);
                Db::table("quick_pay_user_record")->where("uid", $user['id'])->setInc('pay_num');
            } else {
                Db::table("quick_pay_user_record")->insert([
                    'uid'       => $user['id'],
                    'pay_money' => $order['total_fee'],
                    'pay_num'   => 1,
                ]);
            }

            Db::commit();

            $ReportOrder = new ReportOrder();
            $ReportOrder->report_filtering($order);

            return true;
        } catch (\Exception $e) {
            Db::rollback();

            $LogLogic = \think\facade\App::model('Log', 'logic');
            $LogLogic->addInfo('orderHand', "paymentId:{$order['chargefrom']},msg:{$e->getMessage()},line:{$e->getLine()}}", $user['id'], $order['quick_id']);
            return false;
        }
    }

}